#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <fcntl.h>  
#include <sys/socket.h>  
#include <linux/netlink.h>  
#include <sys/types.h>
#include <unistd.h>
#define UEVENT_BUFFER_SIZE 2048  
 
void split(char *src,const char *separator,char **dest,int *num) {
     char *pNext;
     int count = 0;
     if (src == NULL || strlen(src) == 0)
        return;
     if (separator == NULL || strlen(separator) == 0)
        return;
     pNext = strtok(src,separator);
     while(pNext != NULL) {
          *dest++ = pNext;
          ++count;
         pNext = strtok(NULL,separator);
    }
    *num = count;
}
 
int main(void)  
{  
    struct sockaddr_nl client;  
    struct timeval tv;  
    int CppLive, rcvlen, ret;  
    fd_set fds;  
    int buffersize = 1024, num = 0; 
    char *pszFindStr = NULL;
    char aUsbNode[15] = {"/dev/"};
    char command[100];
    char nIntf[15] = {0};
    char *revbuf[8] = {0};
    char *tbuf;
    char usb_path[8] = {0};

    /*创建AF_NETLINK套接字*/
    CppLive = socket(AF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT);  
    /*许该套接字复用其他端口*/
    setsockopt(CppLive, SOL_SOCKET, SO_RCVBUF, &buffersize, sizeof(buffersize));  
 
    /*绑定套接字*/
    memset(&client, 0, sizeof(client));  
    client.nl_family = AF_NETLINK;  
    client.nl_pid = getpid();  
    client.nl_groups = 1; /* receive broadcast message*/  
    bind(CppLive, (struct sockaddr*)&client, sizeof(client));
 
    while (1) {  
        char buf[UEVENT_BUFFER_SIZE] = { 0 };  
        FD_ZERO(&fds);  
        FD_SET(CppLive, &fds);  
        tv.tv_sec = 0;  
        tv.tv_usec = 100 * 1000;  
  	/*监听socket*/
        ret = select(CppLive + 1, &fds, NULL, NULL, &tv);  
        if(ret < 0)  
            continue;  
        if(!(ret > 0 && FD_ISSET(CppLive, &fds)))  
            continue;  
        /* receive data */  
        rcvlen = recv(CppLive, &buf, sizeof(buf), 0);  
        if (rcvlen > 0) {  
//            printf("%s\n-------------\n", buf);  
          /*提取USB节点*/
	   if( (strstr(buf, "add@/device") != NULL) && (strstr(buf, "usbmisc/cdc-wdm") != NULL)){
	    printf("find 1\n");
	    pszFindStr = strstr(buf, "usbmisc/cdc-wdm");
//	    printf("pszFindStr: %s\n",pszFindStr );
//	    printf("buf: %s\n",buf );
	    sscanf(pszFindStr+8,"%s",aUsbNode+5);
	    printf("qmi dev node = %s \r\n",aUsbNode);  	//  /dev/cdc-wdm0

//buf:	    add@/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.4/usbmisc/cdc-wdm0
//          add@/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.4
	   char *tmp=strstr(buf,"usb1");
	   
	   split(tmp,"/",revbuf,&num);
	   
	   strcpy(usb_path,revbuf[2]);
#if 0	   
           printf("usb_path %s\n",usb_path);

     	   for( int i = 0;i < num; i ++) {
         		printf("%s\n",revbuf[i]);
     			}
/***
usb1
1-2
1-2:1.4
usbmisc
cdc-wdm0
****/
#endif
   	   }
	
 	if( (strstr(buf, "move@/device") != NULL)    && (strstr(buf, usb_path) != NULL)  && (strstr(buf, "usb") != NULL)   && (strstr(buf, "net") != NULL)){
        //  move@/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.4/net/wwp0s20u2i4
	    printf("find 1\n");
            pszFindStr = strstr(buf, "net");
            printf("pszFindStr: %s\n",pszFindStr );
            sscanf(pszFindStr ,"%*[a-z]/%[a-z-A-Z0-9]",nIntf );
            printf("network interface : %s\n",nIntf );

	    memset(command,0,sizeof(command));
	    
	    sprintf(command,"ip link set %s down", nIntf);
	    system(command);
	    sprintf(command,"ip link set %s name lte", nIntf);
	    system(command);
	    sprintf(command,"ip link set lte up");
	    system(command);
	   
	  }
	
        }  
    } 
    close(CppLive);  
    return 0;  
} 

